#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using log4net;
using xConnected.Common.Country;
using xConnected.Common.Project;
using xConnected.Core.Model;
using xConnected.Core.Model.ViewModel.xConnected.Core.Model.ViewModel;
using xConnected.Helpers;
using xConnected.Service;

#endregion

namespace xConnected.Controllers
{
    public class PositionController : BaseController<Position>
    {
        private readonly CategoryService _categoryService;
        private readonly CompanyProfileService _companyProfileService;
        private readonly CountryService _countryService;
        private readonly IndustryService _industryService;
        private readonly PositionService _PositionService;
        private readonly TechnologyService _technologyService;
        private readonly TechnologySkillService _technologySkillService;
        private readonly UserService _userService;

        public PositionController(PositionService PositionService, CategoryService categoryService,
                                 TechnologyService technologyService, TechnologySkillService technologySkillService,
                                 CompanyProfileService companyProfileService,
                                 UserService userService, CountryService countryService, IndustryService industryService)
        {
            _PositionService = PositionService;
            _categoryService = categoryService;
            _technologyService = technologyService;
            _technologySkillService = technologySkillService;
            _companyProfileService = companyProfileService;
            _userService = userService;
            _countryService = countryService;
            _industryService = industryService;
        }


        public
            JsonResult ListAdvancedSearchAll
            (AdvancedSearchModelPosition PositionModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (PositionModel.UserId == 1)
                {
                    PositionModel.UserId = _userService.GetUserByUsername(User.Identity.Name).Id;
                }
                var page = _PositionService.AdvancedPagedSearchedAll(PositionModel);
                var Positions = page.Entities.ToList().Select(p => new
                                                                      {
                                                                          p.Id,
                                                                          p.Created,
                                                                          p.Updated,
                                                                          p.Title,
                                                                          p.Description,
                                                                          p.StartDate,
                                                                          p.Duration,
                                                                          p.Location,
                                                                          p.IsDefault,
                                                                          p.Photo,
                                                                          Photo150X150 =
                                                                      p.Photo.Replace("/250X250_", "/150X150_"),
                                                                          Photo80X80 =
                                                                      p.Photo.Replace("/250X250_", "/80X80_"),
                                                                          Photo50X50 =
                                                                      p.Photo.Replace("/250X250_", "/50X50_"),
                                                                          ContractType = p.JobType,
                                                                          ContractTypeText =
                                                                      ProjectRes.ResourceManager.GetString(
                                                                          "JobType" + p.JobType.ToString(),
                                                                          Thread.CurrentThread.CurrentCulture),
                                                                          CountryFlag =
                                                                      "../../Content/img/Flags/" +
                                                                      p.Country.ShortName.ToLower() + ".png",
                                                                          Categories = p.Categories.Select(c => new
                                                                                                                    {
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Id,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Created,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Updated,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Description
                                                                                                                        //    Description
                                                                                                                        //=
                                                                                                                        //CategoryRes
                                                                                                                        //.
                                                                                                                        //ResourceManager
                                                                                                                        //.
                                                                                                                        //GetString
                                                                                                                        //(c
                                                                                                                        //     .
                                                                                                                        //     Key,
                                                                                                                        // Thread
                                                                                                                        //     .
                                                                                                                        //     CurrentThread
                                                                                                                        //     .
                                                                                                                        //     CurrentCulture),
                                                                                                                        //    c
                                                                                                                        //.
                                                                                                                        //Key
                                                                                                                    }),
                                                                          Technologies =
                                                                      p.Technologies.Select(t => new
                                                                                                     {
                                                                                                         t
                                                                                                     .
                                                                                                     Id,
                                                                                                         t
                                                                                                     .
                                                                                                     Created,
                                                                                                         t
                                                                                                     .
                                                                                                     Updated,
                                                                                                         t
                                                                                                     .
                                                                                                     Name
                                                                                                     }),
                                                                          Company = p.CompanyProfile.Title,
                                                                          p.CompanyProfileId,
                                                                          Country = new
                                                                                        {
                                                                                            p.Country.Id,
                                                                                            p.Country.Created,
                                                                                            p.Country.Updated,
                                                                                            Description =
                                                                      CountryRes.ResourceManager.GetString(
                                                                          p.Country.Key,
                                                                          Thread.CurrentThread.CurrentCulture),
                                                                                            p.Country.ShortName
                                                                                        },
                                                                          CountryId = p.Country.Id,
                                                                          Industry = new
                                                                                         {
                                                                                             p.Industry.Id,
                                                                                             p.Industry.Created,
                                                                                             p.Industry.Updated,
                                                                                             p.Industry.Description
                                                                                         },
                                                                          p.IndustryId,
                                                                          UserId = p.CompanyProfile.User.Id
                                                                      });

                return
                    this.JsonNet(
                        new {page.Count, page.CurrentPage, page.PageSize, page.PagesCount, Entities = Positions},
                        JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public
            JsonResult ListAdvancedSearchSome
            (AdvancedSearchModelPosition PositionModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (PositionModel.UserId == 1)
                {
                    PositionModel.UserId = _userService.GetUserByUsername(User.Identity.Name).Id;
                }
                var page = _PositionService.AdvancedPagedSearchedSome(PositionModel);
                var Positions = page.Entities.ToList().Select(p => new
                                                                      {
                                                                          p.Id,
                                                                          p.Created,
                                                                          p.Updated,
                                                                          p.Title,
                                                                          p.Description,
                                                                          p.StartDate,
                                                                          p.Duration,
                                                                          p.Location,
                                                                          p.IsDefault,
                                                                          p.Photo,
                                                                          Photo150X150 =
                                                                      p.Photo.Replace("/250X250_", "/150X150_"),
                                                                          Photo80X80 =
                                                                      p.Photo.Replace("/250X250_", "/80X80_"),
                                                                          Photo50X50 =
                                                                      p.Photo.Replace("/250X250_", "/50X50_"),
                                                                          ContractType = p.JobType,
                                                                          ContractTypeText =
                                                                      ProjectRes.ResourceManager.GetString(
                                                                          "JobType" + p.JobType.ToString(),
                                                                          Thread.CurrentThread.CurrentCulture),
                                                                          CountryFlag =
                                                                      "../../Content/img/Flags/" +
                                                                      p.Country.ShortName.ToLower() + ".png",
                                                                          Categories = p.Categories.Select(c => new
                                                                                                                    {
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Id,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Created,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Updated,
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Description,
                                                                                                                        //    Description
                                                                                                                        //=
                                                                                                                        //CategoryRes
                                                                                                                        //.
                                                                                                                        //ResourceManager
                                                                                                                        //.
                                                                                                                        //GetString
                                                                                                                        //(c
                                                                                                                        //     .
                                                                                                                        //     Key,
                                                                                                                        // Thread
                                                                                                                        //     .
                                                                                                                        //     CurrentThread
                                                                                                                        //     .
                                                                                                                        //     CurrentCulture),
                                                                                                                        c
                                                                                                                    .
                                                                                                                    Key
                                                                                                                    }),
                                                                          Technologies =
                                                                      p.Technologies.Select(t => new
                                                                                                     {
                                                                                                         t
                                                                                                     .
                                                                                                     Id,
                                                                                                         t
                                                                                                     .
                                                                                                     Created,
                                                                                                         t
                                                                                                     .
                                                                                                     Updated,
                                                                                                         t
                                                                                                     .
                                                                                                     Name
                                                                                                     }),
                                                                          Company = p.CompanyProfile.Title,
                                                                          p.CompanyProfileId,
                                                                          Country = new
                                                                                        {
                                                                                            p.Country.Id,
                                                                                            p.Country.Created,
                                                                                            p.Country.Updated,
                                                                                            Description =
                                                                      CountryRes.ResourceManager.GetString(
                                                                          p.Country.Key,
                                                                          Thread.CurrentThread.CurrentCulture),
                                                                                            p.Country.ShortName
                                                                                        },
                                                                          CountryId = p.Country.Id,
                                                                          Industry = new
                                                                                         {
                                                                                             p.Industry.Id,
                                                                                             p.Industry.Created,
                                                                                             p.Industry.Updated,
                                                                                             p.Industry.Description
                                                                                         },
                                                                          p.IndustryId,
                                                                          UserId = p.CompanyProfile.User.Id
                                                                      });

                return
                    this.JsonNet(
                        new {page.Count, page.CurrentPage, page.PageSize, page.PagesCount, Entities = Positions},
                        JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult GetJsonTechnologies()
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var technologiesNames = _technologyService.GetAll().Select(t => new {t.Name});
                IList<string> technologies = new List<string>();
                technologiesNames.ToList().ForEach(t => technologies.Add(t.Name));
                return Json(technologies, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult CreateTechnology(string technologyName, int industryId)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (_technologyService.GetAll().All(t => t.Name != technologyName))
                {
                    var newTech = new Technology
                                      {
                                          Name = technologyName,
                                          IndustryId = industryId
                                      };
                    _technologyService.SaveOrUpdate(newTech);

                    var newTechnologyArray = new List<Technology>();
                    newTechnologyArray.Add(newTech);
                    var technologiesNew = newTechnologyArray.Select(t => new
                                                                             {
                                                                                 t.Id,
                                                                                 t.Created,
                                                                                 t.Updated,
                                                                                 t.Name
                                                                             });
                    return Json(technologiesNew, JsonRequestBehavior.AllowGet);
                }

                var existingTech = _technologyService.GetAll().First(t => t.Name == technologyName);
                var existingTechnologyArray = new List<Technology>();
                existingTechnologyArray.Add(existingTech);
                var technologiesExisting = existingTechnologyArray.Select(t => new
                                                                                   {
                                                                                       t.Id,
                                                                                       t.Created,
                                                                                       t.Updated,
                                                                                       t.Name,
                                                                                       Industry = new
                                                                                                      {
                                                                                                          t.Industry.Id,
                                                                                                          t.Industry.
                                                                                   Created,
                                                                                                          t.Industry.
                                                                                   Updated,
                                                                                                          t.Industry.
                                                                                   Description
                                                                                                      },
                                                                                       Positions =
                                                                                   t.Positions.Select(p => new
                                                                                                              {
                                                                                                                  p.Id,
                                                                                                                  p.
                                                                                                              Created,
                                                                                                                  p.
                                                                                                              Updated,
                                                                                                                  p.
                                                                                                              Title,
                                                                                                                  p.
                                                                                                              Description,
                                                                                                                  ContractType
                                                                                                              =
                                                                                                              p.JobType,
                                                                                                                  p.
                                                                                                              Duration,
                                                                                                                  p.
                                                                                                              Location,
                                                                                                                  p.
                                                                                                              XLocation,
                                                                                                                  p.
                                                                                                              YLocation,
                                                                                                                  Logo =
                                                                                                              p.Photo,
                                                                                                                  p.
                                                                                                              StartDate
                                                                                                              }),
                                                                                       CompanyProfiles =
                                                                                   t.CompanyProfiles.Select(c => new
                                                                                                                     {
                                                                                                                         c
                                                                                                                     .Id,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Created,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Updated,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Title,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Description,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     TagLine,
                                                                                                                         Logo
                                                                                                                     =
                                                                                                                     c.
                                                                                                                     Photo,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Location,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     XLocation,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     YLocation,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     Email,
                                                                                                                         c
                                                                                                                     .
                                                                                                                     PhoneNumber
                                                                                                                     })
                                                                                   });
                return Json(technologiesExisting, JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult Save(Position position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                // if editing existing Position

                var oldCompanyProfile = _companyProfileService.GetById(position.CompanyProfile.Id);

                var selectedCategories = new List<Category>(position.Categories);
                position.Categories.Clear();
                var selectedTechnologies = new List<Technology>(position.Technologies);
                position.Technologies.Clear();
                position.CompanyProfile = oldCompanyProfile;
                // first save the parent entity in order to autogenerate his Id
                _PositionService.SaveOrUpdate(position);

                //create directories for the new Position
                var di = new DirectoryInfo(Server.MapPath("~/Content/Uploads/" +
                                                          Path.Combine(user.Username, "PositionProfiles",
                                                                       position.Id.ToString(), "Photo")));
                di.Create();

                //Save Photo
                var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                var fileNamePhoto = position.Photo.Substring(position.Photo.IndexOf("/250X250_") + 9);
                var directoryPhoto = Server.MapPath("~/Content/Uploads/" +
                                                    Path.Combine(username, "PositionProfiles", position.Id.ToString(),
                                                                 "Photo"));

                var dirPhoto = new DirectoryInfo(directoryPhoto);
                if (!dirPhoto.Exists)
                    dirPhoto.Create();
                foreach (var fi in dirPhoto.GetFiles())
                {
                    if (!fi.FullName.Contains("\\250X250_" + fileNamePhoto) &&
                        !fi.FullName.Contains("\\150X150_" + fileNamePhoto) &&
                        !fi.FullName.Contains("\\80X80_" + fileNamePhoto))
                    {
                        fi.Delete();
                    }
                }
                // then set this Id to all his child relationships foreign key properties
                position.Categories = new List<Category>(selectedCategories);
                position.Technologies = new List<Technology>(selectedTechnologies);
                _PositionService.SaveOrUpdate(position);
                return this.JsonNet(position.Id, JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult Update(Position position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);

                //if the Position belongs to current user save changes
                if (position.CompanyProfile.UserId == user.Id)
                {
                    // load the old entity from the DB and manually set all its new property values
                    var oldPosition = _PositionService.GetById(position.Id);
                    oldPosition.Title = position.Title;
                    oldPosition.Description = position.Description;
                    oldPosition.StartDate = position.StartDate;
                    oldPosition.Duration = position.Duration;
                    oldPosition.Location = position.Location;
                    oldPosition.JobType = position.JobType;
                    oldPosition.CountryId = position.CountryId;

                    var categoriesIds = position.Categories.Select(s => s.Id);
                    var technologiesIds = position.Technologies.Select(s => s.Id);
                    //from all the categories/technologies we find those that exist in the new Position, by ID
                    var categories = _categoryService.GetAll().Where(c => categoriesIds.Contains(c.Id)).ToList();
                    var technologies = _technologyService.GetAll().Where(t => technologiesIds.Contains(t.Id)).ToList();

                    // clean the old relationships and set the new ones
                    oldPosition.Categories.Clear();
                    oldPosition.Technologies.Clear();

                    // categories/technologies require to set their foreign key because they are "one to many" relationship
                    // for the "many to many" it is enough to add it to the list
                    //add the categories/technologies of the new Position to the old Position
                    categories.ForEach(c => oldPosition.Categories.Add(c));
                    technologies.ForEach(t => oldPosition.Technologies.Add(t));

                    _PositionService.SaveOrUpdate(oldPosition);

                    return this.JsonNet(position.Id, JsonRequestBehavior.AllowGet);
                }
                //else if the profile doesn't belong to current user return "error" which means to render "you are not allowed...." message on client side
                return Json("ERROR", JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public
        JsonResult DeletePosition
            (Position
                 position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                _PositionService.Delete(position);
                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public ActionResult CheckSignedIn(int PositionId)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                var userId = user.Id;
                var PositionIds = _PositionService.GetAll().Where(p => p.CompanyProfile.UserId == userId).Select(p => p.Id);

                //if user is signed in and the current profile belongs to that user
                if (user != null && PositionIds.Contains(PositionId))
                {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }
                return Json(false, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Content("ERROR");
            }
        }

        public JsonResult GetKeywordsAutocomplete(string searchTerm = "", int maxRows = 8)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var countries = _countryService.GetAll().Select(l => new
                                                                         {
                                                                             l.Description,
                                                                             l.Id,
                                                                             Type = "la" // as in "lands"
                                                                         });
                var industries = _industryService.GetAll().Select(l => new
                                                                           {
                                                                               l.Description,
                                                                               l.Id,
                                                                               Type = "in"
                                                                           });
                var categories = _categoryService.GetAll().Select(l => new
                                                                           {
                                                                               l.Description,
                                                                               l.Id,
                                                                               Type = "ca"
                                                                           });
                var technologies = _technologyService.GetAll().Select(l => new
                                                                               {
                                                                                   Description = l.Name,
                                                                                   l.Id,
                                                                                   Type = "te"
                                                                               });
                var companies = _companyProfileService.GetAll().Select(l => new
                                                                                {
                                                                                    Description = l.Title,
                                                                                    l.Id,
                                                                                    Type = "co"
                                                                                });
                var keywords = countries.Union(industries).Union(categories).Union(technologies).Union(companies);
                if (searchTerm != "")
                {
                    keywords =
                        keywords.Where(l => l.Description.ToLower().Contains(searchTerm.ToLower())).Take(maxRows);
                }
                return Json(keywords, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult SetAsDefault(Position position)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var PositionProfile = _PositionService.GetById(position.Id);
                var user = PositionProfile.CompanyProfile.User;
                //set isdefault=false to all other profiles that belong to current user
                user.ExpertProfiles.ToList().ForEach(e => e.IsDefault = false);
                user.CompanyProfiles.ToList().ForEach(c => c.IsDefault = false);
                foreach (var company in user.CompanyProfiles)
                {
                    foreach (var PositionX in company.Positions)
                    {
                        PositionX.IsDefault = false;
                    }
                }

                PositionProfile.IsDefault = true;
                _PositionService.SaveOrUpdate(PositionProfile);
                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new { Result = "ERROR", ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }
    }
}